#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/slab.h>

struct Data {
    char name[32];
    int age;
}data;

static int kthread_run_flag = 1;
static int kthread_task(void* arg)
{
    int count = 0;
    const unsigned long wait_time = msecs_to_jiffies(1 * 1000);
    struct Data* data = (struct Data*)arg;
    pr_info("arg -->point=%p data.name=%s, data.age=%d\n", data, data->name, data->age);

    while (kthread_run_flag == 1 && count < 100) {
        pr_info("kthread_run ing ... %d\n", count);

        // mdelay(1000); //--> Bug: 系统无响应, 按键无响应
        set_current_state(TASK_INTERRUPTIBLE);  // 设置可中断模式
        schedule_timeout(wait_time);            // 让出 cpu 控制权

        count++;
    }
    pr_info("kthread exit\n");

    kfree(data);
    return 0;
}

static int __init kthread_test_init(void)
{
    struct task_struct* task;
#if 1
    struct Data* data = kmalloc(sizeof(struct Data), GFP_KERNEL);
    strcpy(data->name, "lilisi");
    data->age = 18;
    pr_info("data point=%p %s,%d\n",data,data->name,data->age);
    task = kthread_run(kthread_task, data, "kthread_task");
#else
    strcpy(data.name, "lilisi");
    data.age = 18;
    task = kthread_run(kthread_task, data, "kthread_task");
#endif
    if (IS_ERR(task)) {
        printk(KERN_ERR "Failed to create thread\n");
        return PTR_ERR(task);
    }

    return 0;
}

static void __exit kthread_test_exit(void)
{
    kthread_run_flag = 0;
    mdelay(2 * 1000); // 等待 kthread_task 退出

    printk(KERN_INFO "Module exiting\n");
}

module_init(kthread_test_init);
module_exit(kthread_test_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Enthusiast");
MODULE_DESCRIPTION("Simple wait_queue example");
